#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
相似度计算
http://www.cnblogs.com/heaad/archive/2011/03/08/1977733.html
'''
critics={'Lisa Rose': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.5,
 'Just My Luck': 3.0, 'Superman Returns': 3.5, 'You, Me and Dupree': 2.5, 
 'The Night Listener': 3.0},
'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5, 
 'Just My Luck': 1.5, 'Superman Returns': 5.0, 'The Night Listener': 3.0, 
 'You, Me and Dupree': 3.5}, 
'Michael Phillips': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.0,
 'Superman Returns': 3.5, 'The Night Listener': 4.0},
'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0,
 'The Night Listener': 4.5, 'Superman Returns': 4.0, 
 'You, Me and Dupree': 2.5},
'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 
 'Just My Luck': 2.0, 'Superman Returns': 3.0, 'The Night Listener': 3.0,
 'You, Me and Dupree': 2.0}, 
'Jack Matthews': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0,
 'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5},
'Toby': {'Snakes on a Plane':4.5,'You, Me and Dupree':1.0,'Superman Returns':4.0}}

from math import sqrt
'''
欧几里得距离计算
'''
def euclidean_distance(matrix, item1,item2):
    target={}
    for item in matrix[item1]:
        if item in matrix[item2]:
            target[item]=1
    if len(target)==0:
        return 0
    #计算距离
    sum_of_squares=sum([pow(matrix[item1][item]-matrix[item2][item],2)
                        for item in matrix[item1] if item in matrix[item2]])
    return 1/(1+ sqrt(sum_of_squares))
    
'''
皮尔逊相关系数评价：智慧编程的算法
http://blog.csdn.net/zimohuakai/article/details/6578791
''' 
def pearson_distance(matrix,item1,item2):
    target={}
    for item in matrix[item1]:
        if item in matrix[item2]:
            target[item]=1
    n=len(target)
    if n==0:
        return 0
    # 评分之和
    sum1= sum(matrix[item1][item] for item in target)
    sum2= sum(matrix[item2][item] for item in target)
    # 评分的平方和
    sqSum1=sum(pow(matrix[item1][item],2) for item in target)
    sqSum2=sum(pow(matrix[item2][item],2) for item in target)
    # 评分的乘积
    pSum=sum(matrix[item1][item]*matrix[item2][item] for item in target)
    #皮尔逊
    num=pSum-(sum1*sum2/n) #乘积的和减去和的乘积除以N
    den=sqrt((sqSum1-pow(sum1, 2)/n)*(sqSum2-pow(sum2, 2)/n))# 不同项平方和减去和的平方除以N，再开方
    if den==0:
        return 0
    return num/den
'''
Jaccard 系数

'''
def jaccard_distance(matrix,item1,item2):
    target={}
    for item in matrix[item1]:
        if item in matrix[item2]:
            target[item]=1
    n=len(target)
    if n==0:
        return 0
    # 评分的平方和
    sqSum1=sum(pow(matrix[item1][item],2) for item in target)
    sqSum2=sum(pow(matrix[item2][item],2) for item in target)
    # 评分的乘积和
    pSum=sum(matrix[item1][item]*matrix[item2][item] for item in target)
    
    den=sqSum1+sqSum2-pSum
    if den==0:
        return 0
    return pSum/den
'''
广义 Jaccard 系数
http://blog.sina.com.cn/s/blog_618985870101jmnp.html
'''
def tanimoto_distance(matrix,item1,item2):
    target={}
    for item in matrix[item1]:
        if item in matrix[item2]:
            target[item]=1
    n=len(target)
    if n==0:
        return 0
    # 评分的平方和
    sqSum1=sum(pow(matrix[item1][item],2) for item in target)
    sqSum2=sum(pow(matrix[item2][item],2) for item in target)
    # 评分的乘积和
    pSum=sum(matrix[item1][item]*matrix[item2][item] for item in target)
    
    den=sqrt(sqSum1)+sqrt(sqSum2)-pSum
    if den==0:
        return 0
    return 1-pSum/den
'''
曼哈顿距离
http://blog.chinaunix.net/uid-18971-id-2800573.html
'''
def manhattan_distance(matrix,item1,item2):
    target={}
    for item in matrix[item1]:
        if item in matrix[item2]:
            target[item]=1
    n=len(target)
    if n==0:
        return 0
    mSum=sum(abs(matrix[item1][item]-matrix[item2][item]) for item in target)
    return mSum
if __name__ == '__main__':
    score=jaccard_distance(critics, 'Toby','Mick LaSalle')
    print(score)
    score=tanimoto_distance(critics, 'Toby','Mick LaSalle')
    print(score)
    pass
            